----------------------------------------------------------------------------------
-- Company:        EECS 452
-- Engineer:       Kurt Metzger
-- 
-- Create Date:    20:00:40 04/21/2008 
-- Design Name: 
-- Module Name:    CamCom - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity CamCom is
    Port ( CamSCL : out  STD_LOGIC;
           CamSDAS : inout  STD_LOGIC;
           command : out  STD_LOGIC_VECTOR (15 downto 0);
           led : out  STD_LOGIC_VECTOR (7 downto 0);
           btn : in  STD_LOGIC_VECTOR (3 downto 0);
           swt : in  STD_LOGIC_VECTOR (7 downto 0);
           clk : in  STD_LOGIC);
end CamCom;

architecture Behavioral of CamCom is

   signal reg_adr : std_logic_vector (7 downto 0) := X"12";
   signal reg_val : std_logic_vector (7 downto 0) := X"34"; -- 34 for cbcr
	signal reg_data : std_logic_vector (7 downto 0);
	signal mode : std_logic_vector (1 downto 0) :="00";
   signal pb : std_logic_vector (3 downto 0);
	signal pb0, pb1, pb2, pb3 : std_logic_vector (1 downto 0);
   signal start_up : std_logic := '1';
   signal leds : std_logic_vector (7 downto 0);
	signal i2c_req, i2c_ack : std_logic :='0';
	type t_state is (s_idle, s_start_read, s_do_read, s_read_done,
	     s_start_write, s_handshake, s_handshake2); 
	signal state, return_state: t_state := s_idle;
   

begin

   command <= reg_adr & reg_val;
	
   led(3 downto 0) <= pb;
   led(7 downto 4) <= i2c_req & i2c_ack & mode;
	
	-- pb 3 load register address
	-- pb 2 load register value
	-- pb 1 read register
	-- pb 0 write register
   
   get_command : process(clk, pb)
   begin
      if rising_edge(clk) then
		
			pb0 <= pb0(0) & pb(0);
			pb1 <= pb1(0) & pb(1);
			pb2 <= pb2(0) & pb(2);
			pb3 <= pb3(0) & pb(3);
         
         if pb3 = "01" then
            reg_adr <= swt;
         end if;
         if pb2 = "01" then
            reg_val <= swt;
         end if;
			
			case state is
				when s_idle =>
					if pb1 = "01" then -- start read operation
						state <= s_start_read;
					end if;
					if pb0 = "01" then -- start three phase write
						state <= s_start_write;
					end if;
					
					--state <= s_start_write;  -- for loop testing
					
				when s_start_read =>
					mode <= "01"; -- write register address only
					return_state <= s_do_read;
					state <= s_handshake;
				when s_do_read =>
					mode <= "10"; -- do two phase read
					return_state <= s_read_done;
					state <= s_handshake;
				when s_read_done =>
					reg_val <= reg_data;
					state <= s_idle;
				
				when s_start_write =>
					mode <= "00";
					return_state <= s_idle;
					state <= s_handshake;
					
				when s_handshake =>
					i2c_req <= '1';
					if i2c_ack = '1' then
						i2c_req <= '0';
						state <= s_handshake2;
					end if;
				when s_handshake2 =>
					if i2c_ack = '0' then
						state <= return_state;
					end if;
			end case;
      end if;
   end process;
   
	
   pbd : entity work.pb_debounce2
   port map (pb_in => btn,
      pb_out => pb,
      clk => clk);
	
	
	cam_i2c : entity work.I2C_camera 
	port map (
		reg_addr => reg_adr,
		send_data => reg_val,
		rcvd_data => reg_data,
		mode => mode,
		req_in => i2c_req,
		ack_out => i2c_ack,
		data => CamSDAS,
		i2c_clk => CamSCL,
		clk => clk);

end Behavioral;

